/*
 ============================================================================
 Name		: SputnikDrawer.cpp
 Author	  : Den Grigorenko
 Copyright   : Copyright (c) 2008 Den123
 Description : CSputnikDrawer - allows to draw sphere and sputniks.
 ============================================================================
 */

#include <eikenv.h>

#include "SputnikDrawer.h"
#include "IconUtils.h"
#include "FontData.h" 

#include <CelestialSphere_0xEEC98BE4.mbg>

CSputnikDrawer :: ~CSputnikDrawer()
{
   delete iIconSphere, iIconSphere = NULL;
   delete iIconGreen,  iIconGreen  = NULL;
   delete iIconGray,   iIconGray   = NULL;
   
   delete iOffScreenBitmapGc,      iOffScreenBitmapGc = NULL;
   delete iOffScreenBitmapDevice,  iOffScreenBitmapDevice = NULL;
   delete iOffScreenBitmap,        iOffScreenBitmap = NULL;
   delete iRotatedOffscreenBitmap, iRotatedOffscreenBitmap = NULL;
}

void CSputnikDrawer :: ConstructL( const CCoeControl* aParent, SFontData* aFontData, TPositionSatelliteInfo* aData, const TDesC& aWaitMess )
{  
   iFontData = aFontData;
   iData = aData;
   iWaitMess = aWaitMess;
   
   iMode = CEikonEnv::Static()->ScreenDevice()->DisplayMode();
   
   // sphere
   iIconSphere = IconUtils :: CreateIconL( EMbmCelestialsphere_0xeec98be4Sphere,  EMbmCelestialsphere_0xeec98be4Sphere_mask  );   
   // used satellite
   iIconGreen  = IconUtils :: CreateIconL( EMbmCelestialsphere_0xeec98be4Green,  EMbmCelestialsphere_0xeec98be4Green_mask  );   
   // unused satellite
   iIconGray  = IconUtils :: CreateIconL( EMbmCelestialsphere_0xeec98be4Gray,  EMbmCelestialsphere_0xeec98be4Gray_mask  );   
   SetContainerWindowL( *aParent );		
   ActivateL();		   
}

void CSputnikDrawer :: SetAngle( TInt aAngle )
{
	iAngle = aAngle;
}


void CSputnikDrawer :: SizeChanged()
{
	CCoeControl :: SizeChanged();
		
    delete iOffScreenBitmapGc;
    delete iOffScreenBitmapDevice;
    delete iOffScreenBitmap;
    delete iRotatedOffscreenBitmap;
	   		
    TRect r = Rect();	
	iOffScreenBitmap = new ( ELeave ) CFbsBitmap();
	iOffScreenBitmap->Create( r.Size(), iMode );
	       
	iRotatedOffscreenBitmap = new ( ELeave ) CFbsBitmap();
	iRotatedOffscreenBitmap->Create( r.Size(), iMode );
	
	iOffScreenBitmapDevice = CFbsBitmapDevice::NewL( iOffScreenBitmap ); 
	   
	iOffScreenBitmapGc  = NULL;
	iOffScreenBitmapDevice->CreateContext( iOffScreenBitmapGc  );   	
}



void CSputnikDrawer :: Draw( const TRect& /*aRect*/ ) const
{
   TRect r = Rect();
   //CWindowGc& gc = SystemGc();
   
   CFbsBitGc& gc = *iOffScreenBitmapGc;
      
   gc.SetBrushColor( KRgbWhite );    
   gc.Clear( r );
   gc.UseFont( iFontData->iFont );
   
   TInt offs = Max( iFontData->iSatLbH, iFontData->iSatLbW ),
           d = Min( r.Width(), r.Height() ) - 2 * offs,
      radius = d / 2;
      
      
   if( iData->NumSatellitesInView() )
   {

     // draw sphere
     IconUtils :: SetIconSizeL( iIconSphere, d, d );
     IconUtils :: DrawIconL( gc, iIconSphere, offs, offs );
          
     // draw satellites
     for( TInt i = 0; i < iData->NumSatellitesInView(); i++ )
     {
         TSatelliteData satData;
         iData->GetSatelliteData( i, satData );
         DrawSputnik( gc, satData, radius, offs ); 
     }      
   }
   else
   {
      // no data -> draw wait str
      gc.SetPenColor( KRgbBlue );	   
      TPoint txtPoint = r.Center();
      txtPoint.iX -= iFontData->iFont->TextWidthInPixels( iWaitMess ) / 2;
      txtPoint.iY -= iFontData->iFont->HeightInPixels() / 2;      
      gc.DrawText( iWaitMess, txtPoint );                  
   } 
   
   
   TPoint point = r.Center();
   TReal  pointSx = r.Width(), pointSy = point.iY,
		  pointNx = 0,         pointNy = point.iY,		   
		  pointEx = point.iX,  pointEy = 0,		   
   	      pointWx = point.iX,  pointWy = r.Height();		   
  
   ConsiderAngle( pointSx,  pointSy,  radius, offs );
   ConsiderAngle( pointNx,  pointNy,  radius, offs );
   ConsiderAngle( pointEx,  pointEy,  radius, offs );
   ConsiderAngle( pointWx,  pointWy,  radius, offs );
   

   gc.SetPenColor( KRgbBlack );	   
   gc.DrawText( _L( "South" ), TPoint( pointSx, pointSy ) );
   gc.DrawText( _L( "North" ), TPoint( pointNx, pointNy ) );
   gc.DrawText( _L( "East" ),  TPoint( pointEx, pointEy ) );
   gc.DrawText( _L( "West" ),  TPoint( pointWx, pointWy ) );
   
        
   CWindowGc& sysGc = SystemGc();
   sysGc.BitBlt( TPoint(0, 0), iOffScreenBitmap );      
}

void CSputnikDrawer :: ConsiderAngle( TReal& aX, TReal& aY, TInt aRadius, TInt anOffs ) const
{
    // �������
    TReal cosAlpha, sinAlpha; 	             		        
    Math :: Cos( cosAlpha, -iAngle * KPi / 180 );	
    Math :: Sin( sinAlpha, -iAngle * KPi / 180 );      
    TReal x0 = aX, y0 = aY;      
    aX = x0 * cosAlpha - y0 * sinAlpha + aRadius + anOffs;
    aY = x0 * sinAlpha + y0 * cosAlpha + aRadius + anOffs;
}



// draw sputnik on the sphere
void CSputnikDrawer :: DrawSputnik( CBitmapContext& aGc, TSatelliteData& aSatData, TInt aRadius, TInt anOffs  ) const
{
   TReal azimuth   = aSatData.Azimuth(),
  	     elevation = aSatData.Elevation();	
   if( !Math :: IsNaN( azimuth ) && !Math :: IsNaN( elevation ) )
   {

      // transform coordinate from spherical in Cartesian.
      TReal cosAzimuth, sinAzimuth, cosElevation; 	             		        
      Math :: Sin( sinAzimuth, ( 90 - azimuth ) * KPi / 180 );
      Math :: Cos( cosAzimuth, ( 90 - azimuth ) * KPi / 180 );	
      Math :: Cos( cosElevation, elevation * KPi / 180 );
        
      TReal x =  cosAzimuth * cosElevation * aRadius,
            y = -sinAzimuth * cosElevation * aRadius;
      
      // �������
      ConsiderAngle( x, y, aRadius, anOffs ); 
      
      
      // calc satellite rect
      TRect satRect( static_cast<TInt>( x - anOffs ), 
                     static_cast<TInt>( y - anOffs ), 
		             static_cast<TInt>( x + anOffs ), 
		             static_cast<TInt>( y + anOffs ) );
      
      
      // draw satellite
      CGulIcon* icon = aSatData.IsUsed() ? iIconGreen : iIconGray;
      IconUtils :: SetIconSizeL( icon, satRect.Width(), satRect.Height() );
      IconUtils :: DrawIconL( aGc, icon, satRect.iTl.iX, satRect.iTl.iY );            

      // draw satellite label        
      TBuf<2> txtId;
      if( aSatData.SatelliteId() < 10 )
         txtId.AppendNum( 0 );
      txtId.AppendNum( aSatData.SatelliteId() );
	   		   
      // calc satellite lable point
      TPoint satTxtPoint( static_cast<TInt>( x - iFontData->iSatLbW / 2 ), static_cast<TInt>( y + iFontData->iSatLbH / 2 ) );

      // draw satellite label	    
      aGc.SetPenColor( aSatData.IsUsed() ? iFontData->iUsedLbColor : iFontData->iUnusedLbColor ); 
      aGc.DrawText( txtId, satTxtPoint );                          
   }	      		
}
